/*
* Created on Tue Jun 13 2023 by Admin
*
* Copyright (c) 2023 shuangdi
*
* description: graph
*
* date: 2024/3/21
*/
<template>
  <div class="rootGraph" :class="{loading:loading}">
    <div id="graphContent" ref="graphContent">
      <div class="custom_bar">
        <div v-if="showSearch" class="option">
          <a-input allowClear
                   v-model:value="searchValue"
                   @keyup.enter="onSearch"
                   placeholder="输入关键字检索节点"
                   style="width: 200px">
            <template #suffix>
              <search-outlined @click="onSearch"/>
            </template>
          </a-input>
        </div>
        <div v-if="showSelectLayout" class="option">
          <a-select v-model:value="currentLayout"
                    style="width: 180px"
                    @change="changeSelect"
                    :getPopupContainer="(triggerNode)=>{return triggerNode.parentNode;}">
            <a-select-option :value="item.id" :key="index" v-for="(item,index) in selectBox">
              {{ item.label }}
            </a-select-option>
          </a-select>
        </div>
        <div class="option icon_box">
          <div v-if="isScale" class="half_content">
            <span class="icon" @click="toolBar('enlarge')" title="放大"><ZoomInOutlined/></span>
            <span class="icon" @click="toolBar('narrow')" title="缩小"><ZoomOutOutlined/></span>
            <span class="icon" @click="toolBar('refresh')" title="刷新布局"><SyncOutlined/></span>
            <span class="icon" @click="toolBar('saveData')" title="保存布局"><AppstoreOutlined/></span>
            <span class="icon" @click="toolBar('center')" title="居中"><CompressOutlined/></span>
            <span class="icon" @click="toolBar('download')" title="下载"><ArrowDownOutlined/></span>
            <span class="icon" @click="toolBar('requestFullscreen')" v-if="!isFullScreen" title="全屏"><FullscreenOutlined/></span>
            <span class="icon" @click="toolBar('exitFullscreen')" v-else title="退出全屏"><FullscreenExitOutlined/></span>
            <span class="icon" @click="showHideToolbar" title="隐藏工具栏"><DoubleLeftOutlined/></span>
          </div>
          <div v-else class="half_content">
            <span class="icon expand" @click="showHideToolbar" title="显示工具栏">
             <MoreOutlined/>
            </span>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import {layouts, unFinishedLayout} from "./config/layoutCfg.js";
import {initGraphMethods} from "./config/index.js";
import {computed, nextTick, onBeforeUnmount, ref, toRaw, watch} from "vue";
import {toolConfig} from './config/graphConfig'
import {
  AppstoreOutlined,
  SearchOutlined,
  FullscreenOutlined,
  ZoomInOutlined,
  ZoomOutOutlined,
  DoubleLeftOutlined,
  CompressOutlined,
  MoreOutlined,
  FullscreenExitOutlined,
  ArrowDownOutlined,
  SyncOutlined
} from "@ant-design/icons-vue"

const props = defineProps({
  graphData: {
    type: Object,
    default: {}
  },
  isNewData: {
    type: Boolean,
    default: true
  }
})
// 图谱dom
const graphContent = ref(null)
// 工具栏是否缩放
let isScale = ref(true)
// 是否全屏
let isFullScreen = ref(false)
// 搜索节点关键字
let searchValue = ref(null)
// 默认布局
let currentLayout = ref('force')
// 显示搜索输入框
let showSearch = ref(toolConfig.showSearch)
// 显示切换布局下拉框
let showSelectLayout = ref(toolConfig.showSelectLayout)
// 图谱对象
let graphObject = null
let loading = ref(true)
let isCluster = computed(() => {
  return !!(props.graphData.otherConfig && props.graphData.otherConfig.cluster)
})
// 布局下拉框
const selectBox = computed(() => {
  return Object.keys(layouts).map(v => {
    return {
      label: `${v}布局`,
      id: v
    }
  })
})
watch(() => unFinishedLayout.value, (data) => {
  setTimeout(() => {
    loading.value = data
  }, 10)
})
watch(() => props.graphData, async (params) => {
  let {data} = params
  if (data === null) {
    destroyedGraph()
    return
  }
  if (!data?.nodes || !data?.edges) {
    return
  }
  await nextTick()
  initGraph(params)
})
onBeforeUnmount(() => {
  destroyedGraph()
})

// 销毁图谱
function destroyedGraph() {
  removeListener()
  graphObject.destroyGraph()
}

// 初始化图谱
function initGraph(nodeData) {
  nodeData = toRaw(nodeData)
  //力导布局force聚类
  if (isCluster.value && currentLayout.value === 'force') {
    const key = nodeData.otherConfig.clusterKey
    nodeData.data.nodes.forEach(v => v.cluster = v[key])
  }
  let paramsObject = {
    params: {
      domNode: graphContent.value,
      layoutOptions: fitCenterData(),
      isNewData: props.isNewData
    },
    nodeData
  }
  graphObject = initGraphMethods(paramsObject)
  // 监听全屏
  fullscreenchange()
}


// 显示隐藏工具栏
function showHideToolbar() {
  isScale.value = !isScale.value
}

// 获取数据
function fitCenterData() {
  let width = graphContent?.value?.clientWidth
  let height = graphContent?.value?.clientHeight
  // 定义一个新对象
  let copyLayouts = null
  if (isCluster.value && (currentLayout.value === 'force' || currentLayout.value === 'force2')) {
    copyLayouts = Object.assign({}, layouts[currentLayout.value], layouts[currentLayout.value].clusterLayouts)
    //力导布局force2聚类
    if (currentLayout.value === 'force2') {
      copyLayouts.clusterLayouts.nodeClusterBy = props.graphData.otherConfig.clusterKey
    }
  } else {
    copyLayouts = Object.assign({}, layouts[currentLayout.value])
  }
  if (copyLayouts.clusterLayouts) delete copyLayouts.clusterLayouts
  copyLayouts.center = [Math.floor(width / 2), Math.floor(height / 2)]
  return copyLayouts
}

// 工具栏方法
function toolBar(v) {
  graphObject.toolBar(v)
}

// 监控是否全屏
function fullscreenchange() {
  document.addEventListener('fullscreenchange', changeFullscreen)
}

// 移除监听事件
function removeListener() {
  document.removeEventListener('fullscreenchange', changeFullscreen)
}

function changeFullscreen() {
  isFullScreen.value = document.fullscreenElement !== null
}

function onSearch() {
  graphObject.searchItem(searchValue.value)
}

// 切换布局
function changeSelect() {
  unFinishedLayout.value = true
  graphObject.changeLayout(fitCenterData())
}
</script>

<style scoped lang="less">
@import "./config/less/index.less";
</style>
